/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Algorithm;

import DAO.PlanificacionDAO;
import DAO.Sesion;
import Model.Camino;
import Model.Empleado;
import Model.EnvioPedido;
import Model.Pedido;
import Model.PuntoMapa;
import Model.Ruta;
import Principals.Utils;
import Model.Vehiculo;
import Presenter.EmpleadoPresenter;
import Presenter.VehiculoPresenter;
import Principals.Constantes;
import Principals.Main;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 *
 * @author sebastian
 */
public class Algoritmo {
    /* ======== INICIO VARIABLES SISTEMA ======== */

    public Boolean EsSimulacion = false;
    public static int CAPACIDAD_MOTO;
    public static int COSTO_KM_MOTO;
    public static int COSTO_H_EXTRA_MOTO;
    public static int V_PROM_MOTO;
    public static int CAPACIDAD_AUTO;
    public static int COSTO_KM_AUTO;
    public static int COSTO_H_EXTRA_AUTO;
    public static int V_PROM_AUTO;
    public static int COSTO_FUERA_PLAZO;
    public static double ALPHA_RUTA;
    public static int MAX_ITERACIONES_RUTA;
    public static int CANT_POBLACION_INICIAL;
    /* ======== FIN VARIABLES SISTEMA ======== */
    public static final int DURACION_TURNO = 8;
    public static final int MAX_DIST = 10;
    public static double PEOR_FITNESS = 0;
    public static double MEJOR_FITNESS = 100000;
    public int TIEMPO_ENTREGA = 1440; //son 24 horas = 1440 minutos
    private double arFitness[];
    private int matPoblacion[][];
    private List<VehiculoDisponible> lstVehiculosDisponibles = new ArrayList<VehiculoDisponible>();
    private List<PuntoMapa> puntos;
    private List<Camino> caminos[];
    private List<Vehiculo> arVehiculos;
    private int CANTIDAD_VEHICULOS;
    private List<Empleado> arEmpleados;
    private List<Pedido> arPedidos;
    public int CANTIDAD_PEDIDOS;
    private Integer[][] distanciasPedido;
    private List<Camino>[][] rutasPedido;
    private Boolean[][] usados;
    private int ACELERADOR_TIEMPO = 30;
    private int x1, x2, y1, y2;

    public static void main(String[] args) throws Exception {
        Main.usrSesion = new Sesion();
        new Algoritmo().load();
    }

    public void load() {
        cargarVariables();
        cargarMapa();
        cargarPedidos();
        precalcularRutas();
        cargarVehiculos();
        cargarEmpleados();
        calcularVehiculosDisponibles();
    }

    public int cantidadVehiculos() {
        cargarVehiculos();
        return CANTIDAD_VEHICULOS;
    }

    public int cantidadEmpleados() {
        cargarEmpleados();
        return arEmpleados.size();
    }

    public Boolean verificarCapacidadVehiculos(int cantPedidos) {
        int cantVehiculos;
        int cantEmpleados;
        Boolean factible = false;
        cantVehiculos = cantidadVehiculos();
        cantEmpleados = cantidadEmpleados();
        if (cantEmpleados > 0 && cantVehiculos > 0) {
            calcularVehiculosDisponibles();
            //calcular si los vehiculos disponibles alcanza para poder con los pedidos que se tiene
            if (cantPedidos <= cantPedidosMaximo()) {
                factible = true;
            }
        }
        return factible;
    }

    public int cantPedidosMaximo() {
        int cantPedidos = 0;
        for (int i = 0; i < lstVehiculosDisponibles.size(); i++) {
            if (lstVehiculosDisponibles.get(i).getObjVehiculo().getTipoVehiculo().getValorString().equalsIgnoreCase("MOTO")) {
                cantPedidos += CAPACIDAD_MOTO;
            }
            if (lstVehiculosDisponibles.get(i).getObjVehiculo().getTipoVehiculo().getValorString().equalsIgnoreCase("AUTO")) {
                cantPedidos += CAPACIDAD_AUTO;
            }
        }
        return cantPedidos;
    }

    //<editor-fold defaultstate="collapsed" desc="cargarVariables">
    private void cargarVariables() {
        CAPACIDAD_MOTO = PlanificacionDAO.getVariableSistemaById(Constantes.IDX_CAPACIDAD_MOTO).getValorNumerico().intValue();
        COSTO_KM_MOTO = PlanificacionDAO.getVariableSistemaById(Constantes.IDX_COSTO_MOTO).getValorNumerico().intValue();
        COSTO_H_EXTRA_MOTO = PlanificacionDAO.getVariableSistemaById(Constantes.IDX_COSTO_H_EXTRA_MOTO).getValorNumerico().intValue();
        V_PROM_MOTO = PlanificacionDAO.getVariableSistemaById(Constantes.IDX_VPROM_MOTO).getValorNumerico().intValue();
        CAPACIDAD_AUTO = PlanificacionDAO.getVariableSistemaById(Constantes.IDX_CAPACIDAD_AUTO).getValorNumerico().intValue();
        COSTO_KM_AUTO = PlanificacionDAO.getVariableSistemaById(Constantes.IDX_COSTO_AUTO).getValorNumerico().intValue();
        COSTO_H_EXTRA_AUTO = PlanificacionDAO.getVariableSistemaById(Constantes.IDX_COSTO_H_EXTRA_AUTO).getValorNumerico().intValue();
        V_PROM_AUTO = PlanificacionDAO.getVariableSistemaById(Constantes.IDX_VPROM_AUTO).getValorNumerico().intValue();
        COSTO_FUERA_PLAZO = PlanificacionDAO.getVariableSistemaById(Constantes.IDX_COSTO_RETRASO).getValorNumerico().intValue();
        ALPHA_RUTA = PlanificacionDAO.getVariableSistemaById(Constantes.IDX_ALPHA_RUTA).getValorNumerico().doubleValue();
        MAX_ITERACIONES_RUTA = PlanificacionDAO.getVariableSistemaById(Constantes.IDX_ITERACIONES_RUTA).getValorNumerico().intValue();
        CANT_POBLACION_INICIAL = PlanificacionDAO.getVariableSistemaById(Constantes.IDX_POBLACION_INICIAL).getValorNumerico().intValue();
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="cargarMapa">
    private void cargarMapa() {
        puntos = PlanificacionDAO.getPuntosMapa();
        caminos = new ArrayList[puntos.size() + 1];
        for (int i = 0; i < caminos.length; i++) {
            caminos[ i] = new ArrayList<Camino>();
        }
        List<Camino> lstCaminos = PlanificacionDAO.getCaminos();
        for (Camino cam : lstCaminos) {
            PuntoMapa ini = cam.getPuntoMapaByPuntoInicial();
            caminos[ ini.getIdPunto()].add(cam);
        }
        //<editor-fold defaultstate="collapsed" desc="debug">
//        System.out.println( "CAMINOS" ) ;
//        for(int i = 1 ; i < caminos.length ; i++){
//            System.out.println( "Ini: (" + puntos.get( i - 1 ).getLatitud()+ " , " + puntos.get( i - 1 ).getLongitud()+ ")" ) ;
//            for( Camino cam : caminos[ i ] ){
//                System.out.print( "Fin: (" + cam.getPuntoMapaByPuntoFinal().getLatitud()+ " , " + cam.getPuntoMapaByPuntoFinal().getLongitud()+ ")\t" ) ;
//                System.out.println( "Dist: " + cam.getDistancia() ) ;
//            }
//            System.out.println() ;
//        }
        //</editor-fold>
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="cargarVehiculos">
    private void cargarVehiculos() {
        verificarVehiculos();
        CANTIDAD_VEHICULOS = (arVehiculos = VehiculoPresenter.obtenerVehiculos()).size();
        // System.out.println("Cantidad de Vehiculos : " + CANTIDAD_VEHICULOS);
        //<editor-fold defaultstate="collapsed" desc="debug">
//        System.out.println( CANTIDAD_VEHICULOS ) ;
//        for( Vehiculo veh : arVehiculos ){
//            System.out.println( veh.getPlaca() + " estado: " + veh.getEstado() ) ;
//        }
        //</editor-fold>
    }

    private void verificarVehiculos() {
        List<Vehiculo> lstVehiculo;
        List<Vehiculo> lstVehiculoRetornados = new ArrayList<Vehiculo>();
        lstVehiculo = VehiculoPresenter.obtenerVehiculos();
        Boolean estado;
        for (int i = 0; i < lstVehiculo.size(); i++) {
            if (lstVehiculo.get(i).getEstado() == 0) {
                estado = verificaRetorno(lstVehiculo.get(i).getIdVehiculo(), lstVehiculo.get(i).getTipoVehiculo().getValorString());
                if (estado) {
                    lstVehiculo.get(i).setEstado(1);
                    lstVehiculoRetornados.add(lstVehiculo.get(i));
                }
            }
        }
        Vehiculo objVehiculo;
        for (int i = 0; i < lstVehiculoRetornados.size(); i++) {
            objVehiculo = lstVehiculoRetornados.get(i);
            VehiculoPresenter.modificarVehiculo(objVehiculo, objVehiculo.getPlaca(), objVehiculo.getTipoVehiculo(), objVehiculo.getAnho());
        }
    }

    private Boolean verificaRetorno(int idVehiculo, String tipoVehiculo) {
        Boolean retorno = false;
        List<Pedido> lstPedidos = new ArrayList<Pedido>();
        lstPedidos = Presenter.PedidoPresenter.pedidosEnRuta();
        List<EnvioPedido> lstEnvioPedido = new ArrayList<EnvioPedido>();
        lstEnvioPedido = Presenter.EnvioPedidoPresenter.buscarEnvioPedido();

        List<Pedido> lstaux = new ArrayList<Pedido>();
        for (int i = 0; i < lstPedidos.size(); i++) {
            for (int j = 0; j < lstEnvioPedido.size(); j++) {
                for (int k = 0; k < lstEnvioPedido.get(j).getPedidos().size(); k++) {
                    lstaux = new ArrayList(lstEnvioPedido.get(j).getPedidos());
                    if (lstPedidos.get(i).getIdPedido() == lstaux.get(k).getIdPedido()) {
                        //una vez que tenemos ubicado el pedido dentro del la lista de EnvioPedido, se verifica si corresponde al vehiculo evaluado
                        if (idVehiculo == lstEnvioPedido.get(j).getVehiculo().getIdVehiculo()) {
                            retorno = calculaEstadoVehiculo(lstPedidos, lstEnvioPedido.get(j).getFechaSalida(), tipoVehiculo);
                            //se aprovecha tanto los vehiculos que retornan como los choferes
                            Empleado objEmpleado = lstEnvioPedido.get(j).getEmpleado();
                            ActualizarEmpleado(objEmpleado);
                            break;
                        }
                    }
                }

            }
        }
        return retorno;
    }

    private Boolean calculaEstadoVehiculo(List<Pedido> lstPedidos, Date fechaSalida, String tipoVehiculo) {
        Boolean estado = false;
        int distanciaAcumulada = 0;
        int puntoAnterior = 0;
        int distanciarecorrida = 0;
        int tiempotranscurrido = 0;
        int posicion = 0;
        for (int i = 0; i < lstPedidos.size(); i++) {
            //buscamos el pedido en el arreglo arpedidos para obetner la posicion adecuada
            for (int j = 0; j < arPedidos.size(); j++) {
                if (arPedidos.get(j).getIdPedido() == lstPedidos.get(i).getIdPedido()) {
                    posicion = j + 1;
                    break;
                }
            }
            int distancia = distanciasPedido[puntoAnterior][posicion];
            distanciaAcumulada = distancia + distanciaAcumulada;
            puntoAnterior = posicion;

            //aprovechamos para verficar si los pedidos ya llegaron a tiempo
            if (tipoVehiculo.equalsIgnoreCase("MOTO")) {
                tiempotranscurrido = Utils.diffHourMinutes(fechaSalida, new Date()) * ACELERADOR_TIEMPO;
                distanciarecorrida = tiempotranscurrido * V_PROM_MOTO;
            } else {
                tiempotranscurrido = Utils.diffHourMinutes(fechaSalida, new Date()) * ACELERADOR_TIEMPO;
                distanciarecorrida = tiempotranscurrido * V_PROM_AUTO;
                if (distanciarecorrida >= distancia) {
                    AcualizaPedidos(lstPedidos.get(i).getIdPedido());
                }
            }

        }
        //se le suma el regreso a la base
        distanciaAcumulada = distanciaAcumulada + distanciasPedido[puntoAnterior][0];
        distanciarecorrida = 0;
        tiempotranscurrido = 0;
        if (tipoVehiculo.equalsIgnoreCase("MOTO")) {
            tiempotranscurrido = Utils.diffHourMinutes(fechaSalida, new Date()) * ACELERADOR_TIEMPO;
            distanciarecorrida = tiempotranscurrido * V_PROM_MOTO;
        } else {
            tiempotranscurrido = Utils.diffHourMinutes(fechaSalida, new Date()) * ACELERADOR_TIEMPO;
            distanciarecorrida = tiempotranscurrido * V_PROM_AUTO;
        }
        if (distanciarecorrida >= distanciaAcumulada) {
            estado = true;
        }
        return estado;
    }

    public void AcualizaPedidos(int idPedido) {
        Pedido objPedido = Presenter.PedidoPresenter.buscarPedidoPorCodigo(idPedido);
        objPedido.setEstado(2);
        Presenter.PedidoPresenter.modificarPedido(objPedido);

    }

    public void ActualizarEmpleado(Empleado objEmpleado) {
        objEmpleado.setEstado(1);
        DAO.EmpleadoDAO.modificarEmpleado(objEmpleado);
    }

    //</editor-fold>
    //<editor-fold defaultstate="collapsed" desc="cargarEmpleados">
    private void cargarEmpleados() {
        arEmpleados = EmpleadoPresenter.empleadosDisponibles();
        //   System.out.println("Cantidad de Empleados :" + arEmpleados.size());
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="cargarPedidos">
    private void cargarPedidos() {
        //verificar el estado del pedido, para actualizar si ya llego o si sigue en ruta
        //falta implementar
        CANTIDAD_PEDIDOS = (arPedidos = Presenter.PedidoPresenter.pedidosPendientes()).size();
        //<editor-fold defaultstate="collapsed" desc="debug">
//        System.out.println( "Pedidos: " + CANTIDAD_PEDIDOS ) ;
//        for( Pedido ped : arPedidos ){
//            System.out.println( ped.getIdPedido() ) ;
//            System.out.println( ped.getCliente().getNombres() ) ;
//            System.out.println( ped.getProducto().getNombre() ) ;
//            System.out.println( ped.getPuntoMapa().getLatitud() + " , " + ped.getPuntoMapa().getLongitud() ) ;
//        }
        //</editor-fold>
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Precalculo de rutas">
    private void precalcularRutas() {
        ArrayList<Integer> indices = new ArrayList<Integer>();
        indices.add(1); // PUNTO ALMACEN
        for (Pedido p : arPedidos) {
            indices.add(p.getPuntoMapa().getIdPunto());
        }

        int n = CANTIDAD_PEDIDOS + 1;
        distanciasPedido = new Integer[n][n];
        rutasPedido = new ArrayList[n][n];

        for (int i = 0; i < indices.size(); i++) {
            for (int j = 0; j < indices.size(); j++) {
                if (i == j) {
                    continue;
                }
                int ini = indices.get(i) - 1;
                int fin = indices.get(j) - 1;
                distanciasPedido[ i][ j] = getTamanhoRuta(rutasPedido[ i][ j] = graspRuta(ini, fin));
            }
        }
    }

    private int getTamanhoRuta(List<Camino> lstCamino) {
        int tam = 0;
        for (Camino cam : lstCamino) {
            tam += cam.getDistancia();
        }
        return tam;
    }

    private boolean valid(int val, int mini, int maxi) {
        return (val >= mini && val <= maxi);
    }

    private List<Camino> getAdyacentes(PuntoMapa pMapa) {
        List<Camino> ady = new ArrayList<Camino>();
        int idxIni = pMapa.getIdPunto();
        for (Camino cam : caminos[ idxIni]) {
            int idxFin = cam.getPuntoMapaByPuntoFinal().getIdPunto();
            if (!valid(cam.getPuntoMapaByPuntoFinal().getLatitud(), x1, x2) || !valid(cam.getPuntoMapaByPuntoFinal().getLongitud(), y1, y2)) {
                continue;
            }
            if (usados[ idxIni][ idxFin]) {
                continue;
            }
            ady.add(cam);
        }
        return ady;
    }

    private List<Camino> getRclRuta(List<Camino> ady) {
        ordenarAdyacentes(ady);

        int beta = ady.get(0).getDistancia();
        int tau = ady.get(ady.size() - 1).getDistancia();

        double inf = beta;
        double sup = (double) beta + (double) (tau - beta) * ALPHA_RUTA;

        List<Camino> rcl = new ArrayList<Camino>();
        for (Camino cam : ady) {
            double dd = cam.getDistancia();
            if (dd >= inf && dd <= sup) {
                rcl.add(cam);
            }
        }
        return rcl;
    }

    private List<Camino> ordenarAdyacentes(List<Camino> ady) {
        Collections.sort(ady, new CustomComparator());
        return ady;
    }

    private class CustomComparator implements Comparator<Camino> {

        @Override
        public int compare(Camino c1, Camino c2) {
            int solucion = 0;
            if (c1.getDistancia() > c2.getDistancia()) {
                solucion = 1;
            } else if (c1.getDistancia() < c2.getDistancia()) {
                solucion = -1;
            }
            return solucion;
        }
    }

    private boolean mejorRuta(List<Camino> sol, List<Camino> best) {
        int tam1 = getTamanhoRuta(sol);
        int tam2 = getTamanhoRuta(best);
        return tam1 <= tam2;
    }

    private PuntoMapa getLast(List<Camino> lstCamino) {
        int n = lstCamino.size();
        return lstCamino.get(n - 1).getPuntoMapaByPuntoFinal();
    }

    private List<Camino> graspRuta(int idxIni, int idxFin) {
        PuntoMapa ini = puntos.get(idxIni);
        PuntoMapa fin = puntos.get(idxFin);
        x1 = Math.min(ini.getLatitud(), fin.getLatitud());
        y1 = Math.min(ini.getLongitud(), fin.getLongitud());
        x2 = Math.max(ini.getLatitud(), fin.getLatitud());
        y2 = Math.max(ini.getLongitud(), fin.getLongitud());
//        x1 = 0 ; y1 = 0 ;
//        x2 = Utils.LARGO_MAPA ; y2 = Utils.ANCHO_MAPA ;


        List<Camino> solucion;
        List<Camino> best = new ArrayList<Camino>();
        List<Camino> ady;
        List<Camino> rcl;
        Camino elegido;
        boolean noExisteRuta;
        int n = puntos.size() + 10;
        usados = new Boolean[n][n];

        for (int k = 0; k < MAX_ITERACIONES_RUTA; k++) {
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) {
                    usados[ i][ j] = false;
                }
            }
            solucion = new ArrayList<Camino>();
            noExisteRuta = false;
            while (solucion.isEmpty() || getLast(solucion).getIdPunto() != fin.getIdPunto()) {
                ady = getAdyacentes(solucion.isEmpty() ? ini : getLast(solucion));
                if (ady.isEmpty()) {
                    noExisteRuta = true;
                    break;
                }
                rcl = getRclRuta(ady);
                elegido = rcl.get(Utils.getRandom(rcl.size()));
                solucion.add(elegido);

                int idInicio = elegido.getPuntoMapaByPuntoInicial().getIdPunto();
                int idFinal = elegido.getPuntoMapaByPuntoFinal().getIdPunto();
                usados[ idInicio][ idFinal] = usados[ idFinal][ idInicio] = true;
            }
            if (noExisteRuta) {
                continue;
            }
            if (best.isEmpty() || mejorRuta(solucion, best)) {
                best = solucion;
            }
        }
        //<editor-fold defaultstate="collapsed" desc="debug">
//        System.out.println("/* ======== DEBE SER ======== */");
//        System.out.print("De: " + ini.getLatitud() + " , " + ini.getLongitud() + "   ");
//        System.out.print("A:  " + fin.getLatitud() + " , " + fin.getLongitud() + "   ");
//        System.out.println();
//
//        System.out.println("/* ======== ESTA COMO ======== */");
//        for (Camino cam : best) {
//            PuntoMapa p1 = cam.getPuntoMapaByPuntoInicial();
//            PuntoMapa p2 = cam.getPuntoMapaByPuntoFinal();
//            System.out.print("De: " + p1.getLatitud() + " , " + p1.getLongitud() + "   ");
//            System.out.print("A:  " + p2.getLatitud() + " , " + p2.getLongitud() + "   ");
//            System.out.println();
//        }
        //</editor-fold>
        return best;
    }
    //</editor-fold>

    //<editor-fold defaultstate="collapsed" desc="Calcular vehiculos disponibles">
    public void calcularVehiculosDisponibles() {
        /*aca se realiza la combinacion de los vehiculos y empleados, dando la cantidad de vehiculos
         disponibles segun la cantidad de empleados que hay disponibles.*/
        List<Vehiculo> motos = new ArrayList<Vehiculo>();
        List<Vehiculo> autos = new ArrayList<Vehiculo>();
        for (Vehiculo veh : arVehiculos) {
            if (veh.getTipoVehiculo().getValorString().equalsIgnoreCase(Constantes.NOMBRE_MOTO_BD)) {
                motos.add(veh);
            } else {
                autos.add(veh);
            }
        }

        lstVehiculosDisponibles = new ArrayList<VehiculoDisponible>();
        int idxMotos = 0;
        int idxAutos = 0;
        //System.out.println("Vehiculos Disponibles (ID)");
        for (Empleado emp : arEmpleados) {
            if (idxMotos < motos.size() && emp.getTipoVehiculo().getValorString().equalsIgnoreCase(Constantes.NOMBRE_MOTO_BD)) {
                lstVehiculosDisponibles.add(new VehiculoDisponible(motos.get(idxMotos++), emp, CAPACIDAD_MOTO));
            } else if (idxAutos < autos.size()) {
                lstVehiculosDisponibles.add(new VehiculoDisponible(autos.get(idxAutos++), emp, CAPACIDAD_AUTO));
            }

        }
        // for(int i=0; i<lstVehiculosDisponibles.size();i++){
        //     System.out.println(lstVehiculosDisponibles.get(i).getObjVehiculo().getIdVehiculo() + "  ");
        // }
        //System.out.println("Cantidad de Vehiculo-Chofer: " + lstVehiculosDisponibles.size() );
    }
    //</editor-fold>

//    //<editor-fold defaultstate="collapsed" desc="Genetico">
    public List<EnvioPedidoAlg> Genetico(List<Double> lstFitnessSolucion) {
        CANTIDAD_PEDIDOS = arPedidos.size();
        matPoblacion = new int[CANT_POBLACION_INICIAL][CANTIDAD_PEDIDOS];
        arFitness = new double[CANT_POBLACION_INICIAL];
        generarPoblacionInicial();
        //0 es MOTO y 1 es AUTO  
        //un 50% de la poblacion se elige para casamiento, debe ser numero par
        int cantidadCasamiento = CANT_POBLACION_INICIAL / 2 + (CANT_POBLACION_INICIAL & 1);
        int[] arrIndividuosSelectos = new int[cantidadCasamiento];

        List<int[][]> lstPoblacionesAnteriores = new ArrayList<int[][]>();
        List<Double> lstFitnessPoblacionesAnteriores = new ArrayList<Double>();
        int cantIteraciones = 0;
        boolean meseta = false;
        int[][] poblacion;
        int individuoSelecto;
        List<Integer> lstIndividuosSelectos = new ArrayList<Integer>();
        while (cantIteraciones++ < 1000) {
            poblacion = matPoblacion;
            individuoSelecto = CalcularFitness(poblacion);
            arrIndividuosSelectos = SeleccionarIndividuos(cantidadCasamiento);
            OperadorCasamiento(arrIndividuosSelectos, cantidadCasamiento);
            //       OperadorMutacion();
            lstFitnessPoblacionesAnteriores.add(MEJOR_FITNESS);
            lstPoblacionesAnteriores.add(matPoblacion);
            lstIndividuosSelectos.add(individuoSelecto);
            if (cantIteraciones > 30) {
                lstFitnessPoblacionesAnteriores.remove(0);
                lstPoblacionesAnteriores.remove(0);
                lstIndividuosSelectos.remove(0);
            }
            if (cantIteraciones > 500) {
                if (CalcularMeseta(lstFitnessPoblacionesAnteriores)) {
                    break;
                }
            }
        }
//        mostrarPoblacion();
        int poblacionElegida = 0;
        if (!meseta) {
            poblacionElegida = 29;
        }
        //mostrarResultado(lstFitnessPoblacionesAnteriores.get(poblacionElegida), cantIteraciones);
        //se va a devolver una lista de los EnvioPedido contenidos en el individuo elegido
        List<EnvioPedidoAlg> lstSolucion;
        lstSolucion = calcularSolucion(lstPoblacionesAnteriores.get(poblacionElegida), lstIndividuosSelectos.get(poblacionElegida));

        double fitness = 0;
        for (int i = 0; i < lstSolucion.size(); i++) {
            fitness = 0;
            fitness = FuncionFitness(new ArrayList(lstSolucion.get(i).getPedidos()), lstSolucion.get(i).getVehiculo().getTipoVehiculo().getValorString(), lstSolucion.get(i).getVehiculo().getIdVehiculo());
            lstFitnessSolucion.add(fitness);
        }
        return lstSolucion;
    }

    public List<EnvioPedidoAlg> calcularSolucion(int[][] poblacionElegida, int indiceElegido) {
        //primero copiamos en un arreglo al individuo elegido
        int[] individuoSelecto = new int[CANTIDAD_PEDIDOS];
        //System.out.println("");
        //System.out.println("solucion:");
        for (int i = 0; i < CANTIDAD_PEDIDOS; i++) {
            individuoSelecto[i] = poblacionElegida[indiceElegido][i];
            //    System.out.print(individuoSelecto[i] + "  ");
        }
        //System.out.println("");
        int numVehiculo;
        List<EnvioPedidoAlg> lstVehiculosEnvio = new ArrayList<EnvioPedidoAlg>();
        List<List<Integer>> lstIdxPedido = new ArrayList<List<Integer>>();

        for (int i = 0; i < CANTIDAD_PEDIDOS; i++) {
            /*en esta parte, el cromosoma lo convertimos en la lista de motos y autos que 
             se usan, de manera que se saca el fitness por cada vehiculo y luego se saca
             la suma total*/
            int indice = 0;
            numVehiculo = individuoSelecto[i];
            Pedido objPedido = arPedidos.get(i);
            //se busca si ya se tiene registrada esa moto
            indice = VerificarExistenciaVehiculoAlg(numVehiculo, lstVehiculosEnvio);
            if (indice != -1) {
                //se agrega el pedido a la moto que se ubico
                lstVehiculosEnvio.get(indice).getPedidos().add(objPedido);
                lstIdxPedido.get(indice).add(i + 1);
                //agregar la ruta
            } else {
                int k = 0;
                Boolean terminoLista = true;
                for (k = 0; k < lstVehiculosDisponibles.size(); k++) {
                    if (lstVehiculosDisponibles.get(k).getObjVehiculo().getIdVehiculo() == numVehiculo) {
                        Vehiculo objVehiculo = lstVehiculosDisponibles.get(k).getObjVehiculo();
                        Empleado objEmpleado = lstVehiculosDisponibles.get(k).getObjEmpleado();
                        /* ======== ENVIO PEDIDO ======== */
                        EnvioPedidoAlg veh = new EnvioPedidoAlg();
                        veh.setEmpleado(objEmpleado);
                        veh.setVehiculo(objVehiculo);
                        veh.setFechaSalida(new Date());
                        veh.getPedidos().add(objPedido);
                        // moto.setFechaRegreso( new Date() ) ;  // LLENAR CON LA FECHA ESTIMADA
                        /* ======== FIN ENVIO PEDIDO ======== */
                        lstIdxPedido.add(new ArrayList());
                        lstIdxPedido.get(lstIdxPedido.size() - 1).add(i + 1);
                        lstVehiculosEnvio.add(veh);
                        break;
                    }
                }


            }
        }

        for (int i = 0; i < lstVehiculosEnvio.size(); i++) {
            List<Pedido> lstPedidos = lstVehiculosEnvio.get(i).getPedidos();
            int idxAnt = 0;
            //System.out.println( "ENVIO PEDIDO: " + (i+1) ) ;
            int tiempoTotalEnvioPedido = 0;
            int puntoAnterior = 0;
            for (int j = 0; j < lstPedidos.size(); j++) {
                List<Camino> lstCamino = rutasPedido[ idxAnt][ lstIdxPedido.get(i).get(j)];
                for (Camino cam : lstCamino) {
                    lstVehiculosEnvio.get(i).getrCamino().add(cam);
                    //System.out.println( cam.getPuntoMapaByPuntoInicial().getIdPunto() + " " + cam.getPuntoMapaByPuntoFinal().getIdPunto() ) ;
                }
                idxAnt = lstIdxPedido.get(i).get(j);
                //aca se calcula el tiempo que se demora cada pedido en llegar a su destino
                tiempoTotalEnvioPedido += calcularTiempoEstimadoPedido(lstVehiculosEnvio.get(i).getVehiculo().getTipoVehiculo().getValorString(), lstPedidos.get(j), tiempoTotalEnvioPedido, puntoAnterior);
            }
            //se registra la fecha estimada para cada envio pedido
            calcularTiempoEstimadoEnvioPedido(lstVehiculosEnvio.get(i), tiempoTotalEnvioPedido);
        }
        return lstVehiculosEnvio;
    }

    public void calcularTiempoEstimadoEnvioPedido(EnvioPedidoAlg objEnvioPedido, int minutosTranscurridos) {
        Date fechaEstimada;
        fechaEstimada = Utils.addMinutesToDate(new Date(), minutosTranscurridos);
        //System.out.println("minutos transcurridos: " + minutosTranscurridos + " fecha estimada: " + fechaEstimada);
        objEnvioPedido.setFechaRegreso(fechaEstimada);
    }

    public int calcularTiempoEstimadoPedido(String tipoVehiculo, Pedido objPedido, int minutosTranscurridos, int puntoAnterior) {
        int distancia = 0;
        Double tiempoEstimado = 0.0;
        int posicion = 0;
        for (int j = 0; j < arPedidos.size(); j++) {
            if (arPedidos.get(j).getIdPedido() == objPedido.getIdPedido()) {
                posicion = j + 1;
                break;
            }
        }
        distancia = distanciasPedido[puntoAnterior][posicion];
        puntoAnterior = posicion;
        if (tipoVehiculo.equalsIgnoreCase(Constantes.NOMBRE_MOTO_BD)) {
            tiempoEstimado = (distancia * 1.0) / V_PROM_MOTO * 60;
            //se le multiplica 60 porque se necesita el tiempo estimado en minutos
        } else if (tipoVehiculo.equalsIgnoreCase(Constantes.NOMBRE_AUTO_BD)) {
            tiempoEstimado = (distancia * 1.0) / V_PROM_AUTO * 60;
        }
        //se le agrega 5 min por el tiempo de descarga
        minutosTranscurridos += tiempoEstimado + 5;
        //System.out.println("minutos trancurridos por pedido=" + minutosTranscurridos);
        Date fechaEstimada;
        if (EsSimulacion) {
            fechaEstimada = Utils.addMinutesToDate(objPedido.getFechaRegistro(), minutosTranscurridos);
        } else {
            fechaEstimada = Utils.addMinutesToDate(new Date(), minutosTranscurridos);
        }
        objPedido.setFechaEntrega(fechaEstimada);
        Presenter.PedidoPresenter.modificarPedido(objPedido);
        puntoAnterior = posicion;
        return minutosTranscurridos;
    }

    public void mostrarResultado(Double fitness, int iteracion) {
        System.out.print("Fitness: ");
        System.out.println(fitness);
    }

    public boolean CalcularMeseta(List<Double> lstFitness) {

        boolean hayMesesta = true;
        double fitnessReferencial = lstFitness.get(0);
        for (int i = 1; i < lstFitness.size(); i++) {
            if (lstFitness.get(i) <= fitnessReferencial) {
                hayMesesta = false;
                break;
            }
        }
        return hayMesesta;
    }

    public void mostrarPoblacion() {
        System.out.println("Poblacion Inicial \n");
        for (int i = 0; i < CANT_POBLACION_INICIAL; i++) {
            for (int j = 0; j < CANTIDAD_PEDIDOS; j++) {
                System.out.print(matPoblacion[i][j] + " ");

            }
            System.out.print("    ----->");
            System.out.print(arFitness[i]);
            System.out.print("    ----->");
            System.out.print(i);

            System.out.println("\n");
        }
    }

    public void OperadorMutacion() { // TO DO: no funciona
        /*solo un porcentaje pequeño de la poblacion se va a mutar, en este caso
         sera un 10% de la problacion*/
        int cantMutaciones = (int) (CANT_POBLACION_INICIAL * 0.1);
        int posicion = 0;
        int individuoSelecto = 0;
        int nuevoGen = 0;
        int[] mutacion = new int[CANTIDAD_PEDIDOS];
        for (int i = 0; i < cantMutaciones; i++) {
            /*se elige un individuo al azar para realizar la mutacion
             * y se elige al azar una posicion para realizar la mutacion*/
            individuoSelecto = (int) (Math.random() * (CANT_POBLACION_INICIAL));
            for (int j = 0; j < CANTIDAD_PEDIDOS; j++) {
                mutacion[j] = matPoblacion[individuoSelecto][j];
            }
            posicion = (int) (Math.random() * (CANTIDAD_PEDIDOS));
            nuevoGen = (int) (Math.random() * (CANTIDAD_VEHICULOS));
            mutacion[posicion] = nuevoGen;
            if (!EsAberracion(mutacion)) {
                Reemplazar(mutacion, individuoSelecto);
            }
        }
    }

    public void OperadorCasamiento(int[] Selectos, int cantidadCasamiento) {
        int[] padre1 = new int[CANTIDAD_PEDIDOS];
        int[] padre2 = new int[CANTIDAD_PEDIDOS];
        int[] hijo1 = new int[CANTIDAD_PEDIDOS];
        int[] hijo2 = new int[CANTIDAD_PEDIDOS];
        int indice = 0;
        int i = 0;
        while (indice < cantidadCasamiento - 1) {
            i = Selectos[indice];
            for (int j = 0; j < CANTIDAD_PEDIDOS; j++) {
                padre1[j] = matPoblacion[i][j];
            }
            indice++;
            i = Selectos[indice];
            for (int j = 0; j < CANTIDAD_PEDIDOS; j++) {
                padre2[j] = matPoblacion[i][j];
            }
            /*ahora que se tienen a ambos padres, se procede a buscar un posicion para realizar el
             crossover y generar a los hijos*/
            int posicion = (int) (Math.random() * (CANTIDAD_PEDIDOS));
            for (int k = 0; k < posicion; k++) {
                hijo1[k] = padre1[k];
                hijo2[k] = padre2[k];
            }
            for (int k = posicion; k < CANTIDAD_PEDIDOS; k++) {
                hijo1[k] = padre2[k];
                hijo2[k] = padre1[k];
            }

            /*ahora se verifica si los nuevos individuos son aberraciones, en caso de serlo, se quedan
             los padres, sino los reemplazan*/
            if (!EsAberracion(hijo1)) {
                Reemplazar(hijo1, indice - 1);
            }
            if (!EsAberracion(hijo2)) {
                Reemplazar(hijo2, indice);
            }
        }
    }

    public void Reemplazar(int[] nuevoIndividuo, int fila) {
        for (int i = 0; i < CANTIDAD_PEDIDOS; i++) {
            matPoblacion[fila][i] = nuevoIndividuo[i];
        }
    }

    public boolean EsAberracion(int[] individuo) {
        boolean aberracion = true;
        int[][] matVerificacion = new int[2][lstVehiculosDisponibles.size()];
        int tam = lstVehiculosDisponibles.size();
        int tamMatrizVerificacion = 0;
        boolean encontrado = false;
        for (int i = 0; i < CANTIDAD_PEDIDOS; i++) {
            //se busca si ya existe en el vector
            int j;
            for (j = 0; j < tam; j++) {
                if (individuo[i] == matVerificacion[0][j]) {
                    matVerificacion[1][j] = matVerificacion[1][j] + 1;
                    encontrado = true;
                    break;
                }
            }
            if (!encontrado) {
                matVerificacion[0][tamMatrizVerificacion] = individuo[i];
                matVerificacion[1][tamMatrizVerificacion] = 1;
                tamMatrizVerificacion++;
            }
        }
        /*una vez llena la matriz de verificacion se pasa a verificar que segun 
         el tipo de vehiculo, no exceda la capacidad maxima*/
        String tipo = "";
        for (int i = 0; i < lstVehiculosDisponibles.size(); i++) {
            //en el caso que se trate de una moto, MOTO=0
            for (int j = 0; j < tam; j++) {
                if (lstVehiculosDisponibles.get(i).getObjVehiculo().getIdVehiculo() == matVerificacion[0][i]) {
                    tipo = lstVehiculosDisponibles.get(i).getObjVehiculo().getTipoVehiculo().getValorString();
                }
            }

            if ((tipo.equalsIgnoreCase(Constantes.NOMBRE_MOTO_BD)) && (matVerificacion[1][i] > CAPACIDAD_MOTO)) {
                aberracion = true;
                break;
            } else {
                aberracion = false;
            }
            //en el caso que se trate de un auto, AUTO=1
            if ((tipo.equalsIgnoreCase(Constantes.NOMBRE_AUTO_BD)) && (matVerificacion[1][i] > CAPACIDAD_AUTO)) {
                aberracion = true;
                break;
            } else {
                aberracion = false;
            }
        }

        return aberracion;
    }

    public List<Integer> calcularListaVehiculosDisponibles() {
        List<Integer> lstVehiculos = new ArrayList<Integer>();
        
        //AGREGAMOS UN ARTIFICIO QUE SI LA CANTIDAD DE PEDIDOS ES MENOR A LA CAPACIDAD DE UNA MOTO QUE LO INSERTE AHI NOMAS
        //solamente si se trata de planificaion, para optimizar la solucion, en simualcion no se evaluaa eso
        if (!EsSimulacion) {
            int cantMotos = 0;
            List<Vehiculo> lstMotos = new ArrayList<Vehiculo>();
            for (VehiculoDisponible veh : lstVehiculosDisponibles) {
                if (veh.getObjVehiculo().getTipoVehiculo().getValorString().equals(Constantes.NOMBRE_MOTO_BD)) {
                    cantMotos++;
                    lstMotos.add(veh.getObjVehiculo());
                }
            }
            //CON ESTO SIEMPRE SE VA A PRIORIZAR LAS MOTOS
            if (CANTIDAD_PEDIDOS < CAPACIDAD_MOTO * cantMotos) {
                for (int i = 0; i < lstMotos.size(); i++) {
                    for (int j = 0; j < CAPACIDAD_MOTO; j++) {
                        lstVehiculos.add(lstMotos.get(i).getIdVehiculo());
                    }
                }
            } else {
                for (VehiculoDisponible vehDisp : lstVehiculosDisponibles) {
                    boolean esAuto = vehDisp.getObjVehiculo().getTipoVehiculo().getValorString().equalsIgnoreCase(Constantes.NOMBRE_AUTO_BD);
                    int capacidad = (esAuto ? CAPACIDAD_AUTO : CAPACIDAD_MOTO);
                    for (int i = 0; i < capacidad; i++) {
                        lstVehiculos.add(vehDisp.getObjVehiculo().getIdVehiculo());
                    }
                }
            }
            //para el caso de simulacion si se sacan TODOS los vehiculos disponibles
        } else {
            for (VehiculoDisponible vehDisp : lstVehiculosDisponibles) {
                    boolean esAuto = vehDisp.getObjVehiculo().getTipoVehiculo().getValorString().equalsIgnoreCase(Constantes.NOMBRE_AUTO_BD);
                    int capacidad = (esAuto ? CAPACIDAD_AUTO : CAPACIDAD_MOTO);
                    for (int i = 0; i < capacidad; i++) {
                        lstVehiculos.add(vehDisp.getObjVehiculo().getIdVehiculo());
                    }
                }
        }


        return lstVehiculos;
    }

    public void generarPoblacionInicial() {
        /*primero determinamos cuantas motos y cuantos autos existe,
         junto con la capacidad que estos tienen, para limitar el random*/
        List<Integer> lstVehiculos;
        /*ahora se procede a generar la poblacion inicial a partir de la lista
         de  vehiculos disponibles para cada uno de los individuos*/
        int indice;
        for (int i = 0; i < CANT_POBLACION_INICIAL; i++) {
            //se debe reiniciar la lista de disponibles por cada individuo
            lstVehiculos = calcularListaVehiculosDisponibles();
            for (int j = 0; j < CANTIDAD_PEDIDOS; j++) {
                /*se genera una posicion aleatoria para elegir un indice de la lista de disponibles y
                 luego se elimina ese indice que se elige*/
//                indice = (int) (Math.random() * (lstVehiculos.size() - 1)) + 1;
                indice = Utils.getRandom(lstVehiculos.size());
                if (indice != -1) {
                    matPoblacion[ i][ j] = lstVehiculos.get(indice);
                    lstVehiculos.remove(indice);
                }
            }
        }
    }

    public int CalcularFitness(int[][] poblacion) {
        int numVehiculo;
        int mejorIndividuo = 0;
        PEOR_FITNESS = 0;
        MEJOR_FITNESS = 100000;
        List<EnvioPedido> lstMotos = new ArrayList<EnvioPedido>();
        List<EnvioPedido> lstAutos = new ArrayList<EnvioPedido>();
        String tipoVehiculo;
        double fitness;
        for (int i = 0; i < CANT_POBLACION_INICIAL; i++) {
            fitness = 0;
            lstMotos = new ArrayList<EnvioPedido>();
            lstAutos = new ArrayList<EnvioPedido>();
            for (int j = 0; j < CANTIDAD_PEDIDOS; j++) {
                /*en esta parte, el cromosoma lo convertimos en la lista de motos y autos que 
                 se usan, de manera que se saca el fitness por cada vehiculo y luego se saca
                 la suma total*/
                int indice = 0;
                numVehiculo = poblacion[i][j];
                tipoVehiculo = IdentificarVehiculo(numVehiculo);
                if (tipoVehiculo.equalsIgnoreCase("MOTO")) {
                    //se busca si ya se tiene registrada esa moto
                    indice = VerificarExistenciaVehiculo(numVehiculo, lstMotos);
                    if (indice != -1) {
                        Pedido objPedido = arPedidos.get(j);
                        //se agrega el pedido a la moto que se ubico
                        lstMotos.get(indice).getPedidos().add(objPedido);
                    } else {
                        int k = 0;
                        boolean terminoLista = true;
                        for (k = 0; k < lstVehiculosDisponibles.size(); k++) {
                            if (lstVehiculosDisponibles.get(k).getObjVehiculo().getIdVehiculo() == numVehiculo) {
                                terminoLista = false;
                                break;
                            }
                        }
                        if (terminoLista) {
                            k = k - 1;
                        }
                        Vehiculo objvehiculo = lstVehiculosDisponibles.get(k).getObjVehiculo();
                        Empleado objEmpleado = lstVehiculosDisponibles.get(k).getObjEmpleado();
                        Pedido objPedido = arPedidos.get(j);
                        Set<Pedido> setPedido = new HashSet<Pedido>();
                        setPedido.add(objPedido);
                        Ruta objRuta = new Ruta();
                        EnvioPedido moto = new EnvioPedido(k, objEmpleado, objvehiculo, objRuta, null, null, new Integer(1), new Integer(1), new BigDecimal(0), setPedido);
                        lstMotos.add(moto);
                    }
                }
                if (tipoVehiculo.equalsIgnoreCase("AUTO")) {
                    //se busca si ya se tiene registrada ese auto
                    indice = VerificarExistenciaVehiculo(numVehiculo, lstAutos);
                    if (indice != -1) {
                        Pedido objPedido = arPedidos.get(j);
                        lstAutos.get(indice).getPedidos().add(objPedido);
                    } else {
                        int k = 0;
                        for (k = 0; k < lstVehiculosDisponibles.size(); k++) {
                            if (lstVehiculosDisponibles.get(k).getObjVehiculo().getIdVehiculo() == numVehiculo) {
                                break;
                            }
                        }
                        Vehiculo objvehiculo = lstVehiculosDisponibles.get(k).getObjVehiculo();
                        Empleado objEmpleado = lstVehiculosDisponibles.get(k).getObjEmpleado();
                        Pedido objPedido = arPedidos.get(j);
                        Set<Pedido> setPedido = new HashSet<Pedido>();
                        setPedido.add(objPedido);
                        Ruta objRuta = new Ruta();
                        EnvioPedido auto = new EnvioPedido(k, objEmpleado, objvehiculo, objRuta, null, null, new Integer(1), new Integer(1), new BigDecimal(0), setPedido);
                        lstMotos.add(auto);
                    }
                }

            }
            /*en este punto ya se tiene dos listas de vehiculos por cada indivicuo de
             la poblacion, ahora sacamos el fitness por cada vehiculo y este se suma hasta
             tener un fitness total*/
            for (int a = 0; a < lstMotos.size(); a++) {
                fitness = fitness + FuncionFitness(new ArrayList(lstMotos.get(a).getPedidos()), "MOTO", lstMotos.get(a).getVehiculo().getIdVehiculo());
            }
            for (int a = 0; a < lstAutos.size(); a++) {
                fitness = fitness + FuncionFitness(new ArrayList(lstAutos.get(a).getPedidos()), "AUTO", lstAutos.get(a).getVehiculo().getIdVehiculo());
            }
            //se almacena el fitness tottal para ese individuo i
            arFitness[i] = fitness;
            if (fitness > PEOR_FITNESS) {
                PEOR_FITNESS = fitness;
            }
            if (fitness < MEJOR_FITNESS) {
                MEJOR_FITNESS = fitness;
                mejorIndividuo = i;
            }
        }
        return mejorIndividuo;
    }

    public double FuncionFitness(List<Pedido> pedidos, String tipoVehiculo, int codVehiculo) {
        double fitness = 0;
        double fitnessTotal = 0;
        /*calculamos el tiempo que demorar ir del punto donde nos encontramos (inicialmente
         el almacen hasta el el siguiente pedido, para multiplicarlo con costo por km segun
         el tipo de vehiculo que sea*/
        //la parada anterior inicial es el almacen, que es el primer registro de la matriz mapa
        int paradaAnterior = 0;
        int siguienteParada = 0;
        int distancia;
        int tiempoDemora;
        int tiempoRuta = 0;;
        Date fechaPedido;
        int tiempoPedido;
        int tiempoTurnoEmpleado;
        for (int i = 0; i < pedidos.size(); i++) {
            fitness = 0;
            distancia = 0;
            tiempoDemora = 0;
            tiempoPedido = 0;
            siguienteParada = -1;
            for (int j = 0; j < arPedidos.size() && siguienteParada == -1; j++) {
                if (arPedidos.get(j).getIdPedido() == pedidos.get(i).getIdPedido()) {
                    siguienteParada = j + 1;
                }
            }
            distancia = distanciasPedido[ paradaAnterior][ siguienteParada];
            tiempoDemora = CalculaTiempoDemora(distancia, tipoVehiculo);
            fechaPedido = pedidos.get(i).getFechaRegistro();
            tiempoPedido = CalculaTiempoRestante(fechaPedido);
            //revisar si el orden coincide con el codigo que se maneja, o si debe hacer un for para buscar ese codigo de vehiculo
            //buscamos a que empleado esta asociado ese pedido
            tiempoTurnoEmpleado = 0;
            for (int j = 0; j < lstVehiculosDisponibles.size(); j++) {
                if (lstVehiculosDisponibles.get(j).getObjVehiculo().getIdVehiculo() == codVehiculo) {
                    tiempoTurnoEmpleado = Utils.diffHourEmpleado(lstVehiculosDisponibles.get(j).getObjEmpleado().getTurno().getHoraFin());
                    break;
                }
            }

            if (tipoVehiculo.equalsIgnoreCase("MOTO")) {
                fitness = COSTO_KM_MOTO * distancia;
            }
            if (tipoVehiculo.equalsIgnoreCase("AUTO")) {
                fitness = COSTO_KM_AUTO * distancia;
            }
            //se resta 5 minutos al tiempo de demora por descargar y entregar el pedido
            tiempoDemora = tiempoDemora + 5;
            tiempoRuta = tiempoRuta + tiempoDemora;
            if (tiempoPedido < tiempoRuta) {
                fitness = fitness + COSTO_FUERA_PLAZO * (tiempoRuta / 60 + 1);
            }
            if (tiempoTurnoEmpleado < tiempoRuta && tiempoTurnoEmpleado > 0) {
                fitness = fitness + COSTO_H_EXTRA_MOTO * (tiempoRuta / 60 + 1);
            }
            paradaAnterior = siguienteParada;
            fitnessTotal = fitnessTotal + fitness;
        }


        return fitnessTotal;
    }

    public int CalculaTiempoRestante(Date fechaPedido) {
        //a la fecha del pedido se le suma el tiempo prometido de la entrega
        Date fechaActual = new Date();
        int tiempoRestante = Utils.diffHourMinutes(fechaPedido, fechaActual);
        return tiempoRestante;
    }

    public int CalculaTiempoDemora(int distancia, String TipoVehiculo) {
        int tiempoDemora = 0;
        if (TipoVehiculo.equalsIgnoreCase("MOTO")) {
            tiempoDemora = distancia / V_PROM_MOTO;
        }
        if (TipoVehiculo.equalsIgnoreCase("AUTO")) {
            tiempoDemora = distancia / V_PROM_AUTO;
        }
        //de esta manaera devolvemos en cantidad de minutos
        tiempoDemora = tiempoDemora * 60;
        return tiempoDemora;
    }

    public int VerificarExistenciaVehiculoAlg(int numVehiculo, List<EnvioPedidoAlg> lstVehiculos) {
        int indice = -1;
        for (int i = 0; i < lstVehiculos.size(); i++) {
            if (lstVehiculos.get(i).getVehiculo().getIdVehiculo() == numVehiculo) {
                indice = i;
                break;
            }
        }
        return indice;
    }

    public int VerificarExistenciaVehiculo(int numVehiculo, List<EnvioPedido> lstVehiculos) {
        int indice = -1;
        for (int i = 0; i < lstVehiculos.size(); i++) {
            if (lstVehiculos.get(i).getVehiculo().getIdVehiculo() == numVehiculo) {
                indice = i;
                break;
            }
        }
        return indice;
    }

    public String IdentificarVehiculo(int numVehiculo) {
        /*se busca el indice del vehiculo en la lista de vehiculos y se identifica el tipo que es*/
        String tipoVehiculo = ""; //puede ser 1 o 0
        //REVISAR ESTE FOR, PUEDE QUE ESTE ORDENADO QUE LA MSMA MANERA QUE EL INDICE QUE
        //SE PASA COMO PARAMETRO SE EL QUE LE CORRESPONE
        for (int i = 0; i < lstVehiculosDisponibles.size(); i++) {
            if (lstVehiculosDisponibles.get(i).getObjVehiculo().getIdVehiculo() == numVehiculo) {
                tipoVehiculo = lstVehiculosDisponibles.get(i).getObjVehiculo().getTipoVehiculo().getValorString();
                break;
            }
        }

        return tipoVehiculo;
    }

    public int[] SeleccionarIndividuos(int cantidadCasamiento) {
        int[] selectos = new int[cantidadCasamiento];
        double max_anterior = 0;
        List<Individuo> lstIndividuos = new ArrayList<Individuo>();
        for (int i = 0; i < CANT_POBLACION_INICIAL; i++) {
            Individuo objIndividuo = new Individuo();
            objIndividuo.setCodigo(i);
            objIndividuo.setMin(max_anterior);
            objIndividuo.setMax(max_anterior + PEOR_FITNESS - arFitness[i]);
            max_anterior = objIndividuo.getMax();
            lstIndividuos.add(objIndividuo);
        }
        //ahora se tiene la lista con el "espacio" que cada individuo ocupa en
        //la ruleta
        int aleatorio = 0;

        for (int index = 0; index < cantidadCasamiento; index++) {
            aleatorio = (int) (Math.random() * (max_anterior - 1)) + 1;
            for (int i = 0; i < CANT_POBLACION_INICIAL; i++) {
                if ((lstIndividuos.get(i).getMin() < aleatorio) && (lstIndividuos.get(i).getMax() > aleatorio)) {
                    selectos[index] = lstIndividuos.get(i).getCodigo();
                    break;
                }
            }
        }
        return selectos;


    }
    //</editor-fold>
}
